package edu.snake.implement.factory;


import edu.snake.core.controller.ArenaController;
import edu.snake.core.controller.GameEngine;
import edu.snake.core.controller.command.Algorithm;
import edu.snake.core.model.Character;
import edu.snake.core.model.Position;
import edu.snake.implement.ConfigConstant;
import edu.snake.implement.command.Sleep;
import edu.snake.implement.command.frog.FrogDirection;
import edu.snake.implement.command.frog.FrogMove;
import edu.snake.implement.command.snake.SnakeMove;
import edu.snake.implement.controller.character.BaseCharacterController;
import edu.snake.implement.controller.character.SnakeController;
import edu.snake.implement.model.character.Frog;
import edu.snake.implement.model.character.Snake;
import edu.snake.implement.model.character.SnakeElement;

import java.util.Deque;
import java.util.LinkedList;

import static edu.snake.implement.factory.PositionFactory.getNewPosition;

public class CharacterControllerFactory {
    public static BaseCharacterController createFrogController(ArenaController arenaController, GameEngine gameEngine) {
        Position position = initFrogRandomCoordinate(arenaController);
        int i = ((int) (Math.random() * 2)) + 1;
        Frog frog = new Frog(position,i);
        arenaController.setToArena(position, frog);
        BaseCharacterController frogController = new BaseCharacterController(frog, arenaController, gameEngine);
        //        Algorithm frogAlgorithm = FrogAlgorithmFactory.createFrogAlgorithm(frogController);
        // begin
        Algorithm algorithm;

        algorithm = new FrogDirection(frogController);
        frogController.add(algorithm);
        algorithm = new FrogMove(frogController);
        frogController.add(algorithm);
        algorithm = new Sleep(frogController, ConfigConstant.millisSnake*ConfigConstant.multiplierDelay);
        frogController.add(algorithm);
        // end
        return frogController;
    }

    public static Position initFrogRandomCoordinate(ArenaController arenaController) {
        boolean correctInit = true;
        while (correctInit) {
            int randomWidth = (int) (Math.random() * arenaController.getModel().getWidth());
            int randomHeight = (int) (Math.random() * arenaController.getModel().getHeight());
            if (arenaController.getFromArena(getNewPosition(randomWidth, randomHeight)) == null) {  // todo check arena cell empty
                return getNewPosition(randomWidth, randomHeight);
            }
        }
        return null;
    }

    public static SnakeController createSnakeController(ArenaController arenaController, int snakeSize, GameEngine gameEngine) {
        //ToDo if arena width less then snake width??
        //    ToDO        Check arena cell empty??  ========
        Snake snake = new Snake(getNewPosition(snakeSize - 1, 0), snakeSize);
        Deque<Character> snakeElementList = new LinkedList<Character>();
        SnakeElement snakeElement = null;
        for (int i = 0; i < snakeSize; i++) {
            Position position = getNewPosition(i, 0);
            arenaController.setToArena(position, snake);
            snakeElement = new SnakeElement(position);
            snakeElementList.add(snakeElement);
        }

        snake.setAllElement(snakeElementList);
        snake.setPosition(snakeElement.getPosition());
        SnakeController snakeController = new SnakeController(snake, arenaController, gameEngine);
        Algorithm algorithm = new SnakeMove(snakeController);
        snakeController.add(algorithm);
        algorithm = new Sleep(snakeController, ConfigConstant.millisSnake);
        snakeController.add(algorithm);
        return snakeController;
    }

    public static Character getNewSnakeElement(Position position) {
        return new SnakeElement(position);
    }

}
